[Ynoi2018] 五彩斑斓的世界
写 Ynoi 题会破防,我试了,是真的。
分块 + 并查集。
开一个值域大小的并查集,这样我们就可以 \(O(1)\) 修改所有块内相同的值。同时通过维护
\(siz\)
数组来快速查询某数出现的次数,且可以随并查集的合并而合并。
接下来进行复杂度分析。注意到,对于本题的修改操作,块内的最大值 \(maxn\) 单调不增。\(maxn\) 最大为 \(10^5+1\),\(m\) 最大为 \(5\times 10^5\),可以视为均摊 \(O(1)\)。
对于整块的修改操作,我们分两种情况讨论:
当 \(2x\ge maxn\) 时,令所有大于 \(x\) 的数减去 \(x\),此时暴力更新 \(maxn\)。
当 \(2x< maxn\) 时,令所有小于等于
\(x\) 的数加上 \(x\),再将块上的 \(tag\) 加 \(x\),表示真实值为整体减 \(tag\)。
对于散块,暴力拆散原来的并查集,直接修改并更新 \(maxn\) 就好。
整块更新是均摊 \(O(1)\),散块更新是均摊
\(O(\sqrt n)\)。
此题卡空间,无法做到 \(O(V\sqrt n)\)
的并查集空间复杂度。考虑将询问离线,在每个块跑一遍询问,答案直接累加。这样我们只需
\(O(V)\) 的空间复杂度。
以上方法无法正确处理 \(a_i=0\)
的情况。注意到,修改操作不会产生新的 \(0\),所以直接在一开始用前缀和处理掉 \(0\) 的询问,之后就不用管了。
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 headless-piston's Blog!
评论